package com.learn.security.theory.message_digest;

import com.learn.security.utils.message_digest.HMACUtil;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * HmacMD算法：含有秘钥的散列函数算法
 * <p>
 * 在MD或SHA的基础上加上了秘钥
 */
public class HMACTest {

    private static final String encodeStr = "HMAC test";

    public static void main(String[] args) {
        HMACUtil();
        jdkHmacMD5();
        bcHmacMD5();

    }

    // 用HMACUtil实现：
    private static void HMACUtil() {
        try {
            // 生产秘钥
            //String key = HMACUtil.initMacKey();

            byte[] keyByte = Hex.decodeHex(new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'});
            String key = HMACUtil.encryptBASE64(keyByte);

            System.err.println("Mac密钥:\n" + key);

            // 加密
            byte[] hmacMD5Bytes = HMACUtil.encryptHMAC(encodeStr.getBytes(), key);
            System.err.println("HMACUtil hmacMD5:" + Hex.encodeHexString(hmacMD5Bytes));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 用jdk实现:
    private static void jdkHmacMD5() {
        try {
            // 初始化KeyGenerator
            KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            //byte[] key = secretKey.getEncoded();
            byte[] key = Hex.decodeHex(new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'});

            // 还原密钥
            SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");
            // 实例化MAC
            Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
            // 初始化MAC
            mac.init(restoreSecretKey);
            // 执行摘要
            byte[] hmacMD5Bytes = mac.doFinal(encodeStr.getBytes());
            System.out.println("jdk hmacMD5:" + Hex.encodeHexString(hmacMD5Bytes));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 用bouncy castle实现:
    private static void bcHmacMD5() {
        try {
            // 初始化KeyGenerator
            KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            //byte[] key = secretKey.getEncoded();
            byte[] key = Hex.decodeHex(new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'});

            HMac hmac = new HMac(new MD5Digest());

            // 必须是16进制的字符，长度必须是2的倍数
            hmac.init(new KeyParameter(key));
            hmac.update(encodeStr.getBytes(), 0, encodeStr.getBytes().length);

            // 执行摘要
            byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
            hmac.doFinal(hmacMD5Bytes, 0);
            System.out.println("bc hmacMD5:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
